#ifndef MYAMG_PROFILE_H
#define MYAMG_PROFILE_H
#include <chrono>
#include <string>
#include <map>
#include <vector>

namespace myamg {
    class Profiler {
    public:
        struct TimeRecord {
            std::string name;
            std::string startLocation;
            std::string endLocation;
            std::chrono::high_resolution_clock::time_point startTime;
            std::chrono::high_resolution_clock::time_point endTime;
            double durationMs;
            bool completed;
        };

        class ScopedTimer {
        public:
            ScopedTimer(Profiler &profiler, const std::string &name, const std::string &location);

            ~ScopedTimer();

        private:
            Profiler &profiler_;
            std::string name_;
        };

        static Profiler &instance();

        void start(const std::string &name, const std::string &location = "");

        void end(const std::string &name, const std::string &location = "");

        void reset();

        void printToConsole(bool detailed = true) const;

        void saveToFile(const std::string &filename, bool detailed = true) const;

        [[nodiscard]] std::string getFormattedReport(bool detailed = true) const;

        [[nodiscard]] const std::vector<TimeRecord> &getRecords() const;

    private:
        Profiler() = default;

        ~Profiler() = default;

        Profiler(const Profiler &) = delete;

        Profiler &operator=(const Profiler &) = delete;

        std::vector<TimeRecord> records_;
        std::map<std::string, TimeRecord> activeTimers_;
    };

#define PROFILE_SCOPE(name) \
myamg::Profiler::ScopedTimer timer_##__COUNTER__(myamg::Profiler::instance(), name, __FILE__ ":" + std::to_string(__LINE__))

#define PROFILE_FUNCTION() \
myamg::Profiler::ScopedTimer timer_##__COUNTER__(myamg::Profiler::instance(), __FUNCTION__, __FILE__ ":" + std::to_string(__LINE__))
}

#endif //MYAMG_PROFILE_H
